/*
 * @(#) $Header$
 *
 * Copyright (C) 2007  Forklabs Daniel Léonard
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

package ca.forklabs.media.jai;

import java.awt.image.DataBuffer;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.RenderableImage;
import java.net.URL;
import javax.media.jai.BorderExtender;
import javax.media.jai.ImageFunction;
import javax.media.jai.Interpolation;
import javax.media.jai.ParameterBlockJAI;
import javax.media.jai.ROI;
import javax.media.jai.operator.DFTDataNature;
import javax.media.jai.operator.DFTDescriptor;
import javax.media.jai.operator.DFTScalingType;
import javax.media.jai.operator.IDFTDescriptor;
import javax.media.jai.registry.RenderableRegistryMode;
import javax.media.jai.registry.RenderedRegistryMode;
import com.sun.media.jai.codec.ImageDecodeParam;
import com.sun.media.jai.codec.ImageEncodeParam;
import ca.forklabs.baselib.util.Pair;

/**
 * Class {@code ParameterBlockUtil} is a factory for JAI parameter blocks. This
 * class can be extended to provide more methods and only have one class name to
 * remember.
 *
 * @author   <a href="mailto:forklabs at gmail.com?subject=ca.forklabs.media.jai.ParameterBlockUtil">Daniel Léonard</a>
 * @version $Revision$
 */
public class ParameterBlockUtil {

//---------------------------
// Constructors
//---------------------------

   /**
    * Only allow factory subclasses.
    */
   protected ParameterBlockUtil() {
   // nothing
      }


//---------------------------
// Class methods
//---------------------------

   /**
    * Creates a {@link ParameterBlockJAI} for the specified operation in
    * rendered mode.
    * @param   name   the name of the operation.
    * @param   source   the source image.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createParameterBlock(String name, RenderedImage source) {
      String mode = RenderedRegistryMode.MODE_NAME;
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, mode, source);
      return pb;
      }

   /**
    * Creates a {@link ParameterBlockJAI} for the specified operation and
    * parameters in rendered mode.
    * @param   name   the name of the operation.
    * @param   source   the source image.
    * @param   parameters   the parameters.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createParameterBlock(String name, RenderedImage source, Pair<String, ?>... parameters) {
      String mode = RenderedRegistryMode.MODE_NAME;
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, mode, source, parameters);
      return pb;
      }

   /**
    * Creates a {@link ParameterBlockJAI} for the specified operation in
    * renderable mode.
    * @param   name   the name of the operation.
    * @param   source   the source image.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createParameterBlock(String name, RenderableImage source) {
      String mode = RenderableRegistryMode.MODE_NAME;
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, mode, source);
      return pb;
      }

   /**
    * Creates a {@link ParameterBlockJAI} for the specified operation and
    * parameters in renderable mode.
    * @param   name   the name of the operation.
    * @param   source   the source image.
    * @param   parameters   the parameters.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createParameterBlock(String name, RenderableImage source, Pair<String, ?>... parameters) {
      String mode = RenderableRegistryMode.MODE_NAME;
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, mode, source, parameters);
      return pb;
      }

   /**
    * Creates a {@link ParameterBlockJAI} for the specified operation.
    * @param   name   the name of the operation.
    * @param   mode   the render mode.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createParameterBlock(String name, String mode) {
      ParameterBlockJAI pb = new ParameterBlockJAI(name, mode);
      return pb;
      }

   /**
    * Creates and fills a {@link ParameterBlockJAI}.
    * @param   operation   the name of the JAI operation.
    * @param   mode   the mode of the operation.
    * @param   source   the source image.
    * @param   parameters   the list of parameters.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createParameterBlock(String operation, String mode, Object source, Pair<String, ?>... parameters) {
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(operation, mode);
      if (null != source) {
         pb.addSource(source);
         }
      for (Pair<String, ?> parameter : parameters) {
         String name = parameter.getFirst();
         Object value = parameter.getSecond();
         pb.setParameter(name, value);
         }
      return pb;
      }


//-----------------
// addconst
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>addconst</em>.
    * @param   source   the source image.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createAddConstParameterBlock(RenderedImage source) {
      double constant = 0.0;
      ParameterBlockJAI pb = ParameterBlockUtil.createAddConstParameterBlock(source, constant);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>addconst</em>.
    * @param   source   the source image.
    * @param   constant   the constant to be added.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createAddConstParameterBlock(RenderedImage source, double constant) {
      double[] constants = new double[] { constant, };
      ParameterBlockJAI pb = ParameterBlockUtil.createAddConstParameterBlock(source, constants);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>addconst</em>.
    * @param   source   the source image.
    * @param   constants   the constants to be added.
    * @return   the parameter block.
    */
   @SuppressWarnings({ "nls", "unchecked" })
   public static ParameterBlockJAI createAddConstParameterBlock(RenderedImage source, double[] constants) {
      String name = "addconst";
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source,
                                                                     Pair.makePair("constants", constants));
      return pb;
      }


//-----------------
// bandmerge
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>bandmerge</em>.
    * @param   source0   the first source image.
    * @param   source1   the second source image.
    * @param   sourcen   other source images.
    * @return   the parameter block.
    */
   @SuppressWarnings("nls")
   public static ParameterBlockJAI createBandMergeParameterBlock(RenderedImage source0, RenderedImage source1, RenderedImage... sourcen) {
      String name = "bandmerge";
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source0);
      pb.addSource(source1);
      for (RenderedImage source : sourcen) {
         pb.addSource(source);
         }
      return pb;
      }


//-----------------
// bandselect
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>bandselect</em>.
    * @param   source   the source image.
    * @param   indices   the bands to select.
    * @return   the parameter block.
    */
   @SuppressWarnings({ "nls", "unchecked" })
   public static ParameterBlockJAI createBandSelectParameterBlock(RenderedImage source, int... indices) {
      String name = "bandselect";
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source,
                                                                     Pair.makePair("bandIndices", indices));
      return pb;
      }


//-----------------
// border
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>border</em>.
    * @param   source   the source image.
    * @param   pad   the border size all around the image.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createBorderParameterBlock(RenderedImage source, int pad) {
      BorderExtender extender = BorderExtender.createInstance(BorderExtender.BORDER_ZERO);
      ParameterBlockJAI pb = ParameterBlockUtil.createBorderParameterBlock(source, pad, extender);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>border</em>.
    * @param   source   the source image.
    * @param   pad   the border size all around the image.
    * @param   extender   the type of border.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createBorderParameterBlock(RenderedImage source, int pad, BorderExtender extender) {
      int left_pad = pad;
      int right_pad = pad;
      int top_pad = pad;
      int bottom_pad = pad;
      ParameterBlockJAI pb = ParameterBlockUtil.createBorderParameterBlock(source, left_pad, right_pad, top_pad, bottom_pad, extender);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>border</em>.
    * @param   source   the source image.
    * @param   left_pad   the border size on the left.
    * @param   right_pad   the border size on the right.
    * @param   top_pad   the border size on the top.
    * @param   bottom_pad   the border size on the bottom.
    * @param   extender   the type of border.
    * @return   the parameter block.
    */
   @SuppressWarnings({ "nls", "boxing", "unchecked" })
   public static ParameterBlockJAI createBorderParameterBlock(RenderedImage source, int left_pad, int right_pad, int top_pad, int bottom_pad, BorderExtender extender) {
      String name = "border";
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source,
                                                                     Pair.makePair("leftPad", left_pad),
                                                                     Pair.makePair("rightPad", right_pad),
                                                                     Pair.makePair("topPad", top_pad),
                                                                     Pair.makePair("bottomPad", bottom_pad),
                                                                     Pair.makePair("type", extender));
      return pb;
      }


//-----------------
// boxfilter
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>boxfilter</em>.
    * @param   source   the source image.
    * @param   size   the size of the box.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createBoxFilterParameterBlock(RenderedImage source, int size) {
      int width = size;
      int height = size;
      int key_x = size / 2;
      int key_y = size / 2;
      ParameterBlockJAI pb = ParameterBlockUtil.createBoxFilterParameterBlock(source, width, height, key_x, key_y);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>boxfilter</em>.
    * @param   source   the source image.
    * @param   width   the width of the box.
    * @param   height   the height of the box.
    * @param   key_x   the <em>x</em> position of the key element.
    * @param   key_y   the <em>y</em> position of the key element.
    * @return   the parameter block.
    */
   @SuppressWarnings({ "nls", "unchecked", "boxing" })
   public static ParameterBlockJAI createBoxFilterParameterBlock(RenderedImage source, int width, int height, int key_x, int key_y) {
      String name = "boxfilter";
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source,
                                                                     Pair.makePair("width", width),
                                                                     Pair.makePair("height", height),
                                                                     Pair.makePair("xKey", key_x),
                                                                     Pair.makePair("yKey", key_y));
      return pb;
      }


//-----------------
// constant
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>constant</em>.
    * @param   width   the width of the image.
    * @param   height   the height of the image.
    * @param   values   the values for each band.
    * @return   the parameter block.
    */
   @SuppressWarnings({ "nls", "unchecked", "boxing" })
   public static ParameterBlockJAI createConstantParameterBlock(float width, float height, Number[] values) {
      String name = "constant";
      RenderedImage source = null;
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source,
                                                                     Pair.makePair("width", width),
                                                                     Pair.makePair("height", height),
                                                                     Pair.makePair("bandValues", values));
      return pb;
      }


//-----------------
// crop
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>crop</em>.
    * @param   source   the source image.
    * @param   x   the x origin of the cropping operation.
    * @param   y   the y origin of the cropping operation.
    * @param   width   the width of the cropping operation.
    * @param   height   the height of the cropping operation.
    * @return   the parameter block.
    */
   @SuppressWarnings({ "nls", "unchecked", "boxing" })
   public static ParameterBlockJAI createCropParameterBlock(RenderedImage source, float x, float y, float width, float height) {
      String name = "crop";
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source,
                                                                     Pair.makePair("x", x),
                                                                     Pair.makePair("y", y),
                                                                     Pair.makePair("width", width),
                                                                     Pair.makePair("height", height));
      return pb;
      }


//-----------------
// dft
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>dft</em>.
    * @param   source   the source image.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createDFTParameterBlock(RenderedImage source) {
      DFTScalingType type = DFTDescriptor.SCALING_NONE;
      DFTDataNature nature = DFTDescriptor.REAL_TO_COMPLEX;
      ParameterBlockJAI pb = ParameterBlockUtil.createDFTParameterBlock(source, type, nature);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>dft</em>.
    * @param   source   the source image.
    * @param   type   the type of scaling.
    * @param   nature   the nature of the data.
    * @return   the parameter block.
    */
   @SuppressWarnings({ "nls", "unchecked" })
   public static ParameterBlockJAI createDFTParameterBlock(RenderedImage source, DFTScalingType type, DFTDataNature nature) {
      String name = "dft";
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source,
                                                                     Pair.makePair("scalingType", type),
                                                                     Pair.makePair("dataNature", nature));
      return pb;
      }


//-----------------
// exp
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>exp</em>.
    * @param   source   the source image.
    * @return   the parameter block.
    */
   @SuppressWarnings("nls")
   public static ParameterBlockJAI createExpParameterBlock(RenderedImage source) {
      String name = "exp";
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source);
      return pb;
      }


//-----------------
// extrema
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>extrema</em>.
    * @param   source   the source image.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createExtremaParameterBlock(RenderedImage source) {
      ROI roi = null;
      int x_period = 1;
      int y_period = 1;
      ParameterBlockJAI pb = ParameterBlockUtil.createExtremaParameterBlock(source, roi, x_period, y_period);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>extrema</em>.
    * @param   source   the source image.
    * @param   roi   the region of interest.
    * @param   x_period   the horizontal sampling.
    * @param   y_period   the vertical sampling.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createExtremaParameterBlock(RenderedImage source, ROI roi, int x_period, int y_period) {
      boolean save_locations = false;
      int max_runs = 1;
      ParameterBlockJAI pb = ParameterBlockUtil.createExtremaParameterBlock(source, roi, x_period, y_period, save_locations, max_runs);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>extrema</em>.
    * @param   source   the source image.
    * @param   roi   the region of interest.
    * @param   x_period   the horizontal sampling.
    * @param   y_period   the vertical sampling.
    * @param   save_locations   whether or not to save the extrema locations.
    * @param   max_runs   the number of extrema locations to save for both the
    *                     minima and the maxima.
    * @return   the parameter block.
    */
   @SuppressWarnings({ "nls", "unchecked", "boxing" })
   public static ParameterBlockJAI createExtremaParameterBlock(RenderedImage source, ROI roi, int x_period, int y_period, boolean save_locations, int max_runs) {
      String name = "extrema";
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source,
                                                                     Pair.makePair("roi", roi),
                                                                     Pair.makePair("xPeriod", x_period),
                                                                     Pair.makePair("yPeriod", y_period),
                                                                     Pair.makePair("saveLocations", save_locations),
                                                                     Pair.makePair("maxRuns", max_runs));
      return pb;
      }


//-----------------
// fileload
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>fileload</em>.
    * @param   filename   the name of the file containing the image.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createFileLoadParameterBlock(String filename) {
      ImageDecodeParam param = null;
      ParameterBlockJAI pb = ParameterBlockUtil.createFileLoadParameterBlock(filename, param);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>fileload</em>.
    * @param   filename   the name of the file containing the image.
    * @param   param   decoding parameters.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createFileLoadParameterBlock(String filename, ImageDecodeParam param) {
      boolean check_local = true;
      ParameterBlockJAI pb = ParameterBlockUtil.createFileLoadParameterBlock(filename, param, check_local);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>fileload</em>.
    * @param   filename   the name of the file containing the image.
    * @param   param   decoding parameters.
    * @param   check_local   if the image is local.
    * @return   the parameter block.
    */
   @SuppressWarnings({ "nls", "unchecked", "boxing" })
   public static ParameterBlockJAI createFileLoadParameterBlock(String filename, ImageDecodeParam param, boolean check_local) {
      String name = "fileload";
      RenderedImage source = null;
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source,
                                                                     Pair.makePair("filename", filename),
                                                                     Pair.makePair("param", param),
                                                                     Pair.makePair("checkFileLocally", check_local));
      return pb;
      }


//-----------------
// filestore
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>filestore</em>.
    * @param   source   the source image.
    * @param   filename   the name of the file containing the image.
    * @return   the parameter block.
    */
   @SuppressWarnings("nls")
   public static ParameterBlockJAI createFileStoreParameterBlock(RenderedImage source, String filename) {
      String format = "TIFF";

      int dot = filename.lastIndexOf('.');
      boolean dot_exists = (-1 != dot);
      boolean more_text_after_dot = (filename.length() > (dot + 1));
      if (dot_exists && more_text_after_dot) {
         format = filename.substring(dot + 1);
         }

      ParameterBlockJAI pb = ParameterBlockUtil.createFileStoreParameterBlock(source, filename, format);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>filestore</em>.
    * @param   source   the source image.
    * @param   filename   the name of the file containing the image.
    * @param   format   the image format.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createFileStoreParameterBlock(RenderedImage source, String filename, String format) {
      ImageEncodeParam param = null;
      ParameterBlockJAI pb = ParameterBlockUtil.createFileStoreParameterBlock(source, filename, format, param);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>filestore</em>.
    * @param   source   the source image.
    * @param   filename   the name of the file containing the image.
    * @param   format   the image format.
    * @param   param   decoding parameters.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createFileStoreParameterBlock(RenderedImage source, String filename, String format, ImageEncodeParam param) {
      boolean check_local = true;
      ParameterBlockJAI pb = ParameterBlockUtil.createFileStoreParameterBlock(source, filename, format, param, check_local);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>filestore</em>.
    * @param   source   the source image.
    * @param   filename   the name of the file containing the image.
    * @param   format   the image format.
    * @param   param   decoding parameters.
    * @param   check_local   if the image is local.
    * @return   the parameter block.
    */
   @SuppressWarnings({ "nls", "unchecked", "boxing" })
   public static ParameterBlockJAI createFileStoreParameterBlock(RenderedImage source, String filename, String format, ImageEncodeParam param , boolean check_local) {
      String name = "filestore";
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source,
                                                                     Pair.makePair("filename", filename),
                                                                     Pair.makePair("format", format),
                                                                     Pair.makePair("param", param),
                                                                     Pair.makePair("checkFileLocally", check_local));
      return pb;
      }


//-----------------
// format
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>format</em>.
    * @param   source   the source image.
    * @param   type   the data type.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createFormatParameterBlock(RenderedImage source, FormatDataType type) {
      int raw_type = type.getDataBufferType();
      ParameterBlockJAI pb = ParameterBlockUtil.createFormatParameterBlock(source, raw_type);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>format</em>.
    * @param   source   the source image.
    * @param   type   the data type.
    * @return   the parameter block.
    * @see   DataBuffer
    */
   @SuppressWarnings({ "nls", "unchecked", "boxing" })
   public static ParameterBlockJAI createFormatParameterBlock(RenderedImage source, int type) {
      String name = "format";
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source,
                                                                     Pair.makePair("dataType", type));
      return pb;
      }


//-----------------
// idft
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>idft</em>.
    * @param   source   the source image.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createIDFTParameterBlock(RenderedImage source) {
      DFTScalingType type = IDFTDescriptor.SCALING_DIMENSIONS;
      DFTDataNature nature = IDFTDescriptor.COMPLEX_TO_REAL;
      ParameterBlockJAI pb = ParameterBlockUtil.createIDFTParameterBlock(source, type, nature);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>idft</em>.
    * @param   source   the source image.
    * @param   type   the type of scaling.
    * @param   nature   the nature of the data.
    * @return   the parameter block.
    */
   @SuppressWarnings({ "nls", "unchecked" })
   public static ParameterBlockJAI createIDFTParameterBlock(RenderedImage source, DFTScalingType type, DFTDataNature nature) {
      String name = "idft";
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source,
                                                                     Pair.makePair("scalingType", type),
                                                                     Pair.makePair("dataNature", nature));
      return pb;
      }


//-----------------
// imagefunction
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>imagefunction</em>.
    * @param   function   the function.
    * @param   width   the width.
    * @param   height   the height.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createImageFunctionParameterBlock(ImageFunction function, int width, int height) {
      float sx = 1.0f;
      float sy = 1.0f;
      float tx = 0.0f;
      float ty = 0.0f;
      ParameterBlockJAI pb = ParameterBlockUtil.createImageFunctionParameterBlock(function, width, height, sx, sy, tx, ty);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>imagefunction</em>.
    * @param   function   the function.
    * @param   width   the width.
    * @param   height   the height.
    * @param   sx   the scaling factor in the <em>x</em> dimension.
    * @param   sy   the scaling factor in the <em>y</em> dimension.
    * @param   tx   the translation value in the <em>x</em> dimension.
    * @param   ty   the translation value in the <em>y</em> dimension.
    * @return   the parameter block.
    */
   @SuppressWarnings({ "nls", "boxing", "unchecked" })
   public static ParameterBlockJAI createImageFunctionParameterBlock(ImageFunction function, int width, int height, float sx, float sy, float tx, float ty) {
      String name = "imagefunction";
      RenderedImage source = null;
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source,
                                                                     Pair.makePair("function", function),
                                                                     Pair.makePair("width", width),
                                                                     Pair.makePair("height", height),
                                                                     Pair.makePair("xScale", sx),
                                                                     Pair.makePair("yScale", sy),
                                                                     Pair.makePair("xTrans", tx),
                                                                     Pair.makePair("yTrans", ty));
      return pb;
      }


//-----------------
// log
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>log</em>.
    * @param   source   the source image.
    * @return   the parameter block.
    */
   @SuppressWarnings("nls")
   public static ParameterBlockJAI createLogParameterBlock(RenderedImage source) {
      String name = "log";
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source);
      return pb;
      }


//-----------------
// mean
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>mean</em>.
    * @param   source   the source image.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createMeanParameterBlock(RenderedImage source) {
      int h_sampling = 1;
      int v_sampling = 1;
      ParameterBlockJAI pb = ParameterBlockUtil.createMeanParameterBlock(source, h_sampling, v_sampling);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>mean</em>.
    * @param   source   the source image.
    * @param   roi   the region of interest.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createMeanParameterBlock(RenderedImage source, ROI roi) {
      int h_sampling = 1;
      int v_sampling = 1;
      ParameterBlockJAI pb = ParameterBlockUtil.createMeanParameterBlock(source, roi, h_sampling, v_sampling);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>mean</em>.
    * @param   source   the source image.
    * @param   h_sampling   the horizontal sampling rate.
    * @param   v_sampling   the vertical sampling rate.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createMeanParameterBlock(RenderedImage source, int h_sampling, int v_sampling) {
      ROI roi = null;
      ParameterBlockJAI pb = ParameterBlockUtil.createMeanParameterBlock(source, roi, h_sampling, v_sampling);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>mean</em>.
    * @param   source   the source image.
    * @param   roi   the region of interest.
    * @param   h_sampling   the horizontal sampling rate.
    * @param   v_sampling   the vertical sampling rate.
    * @return   the parameter block.
    */
   @SuppressWarnings({ "nls", "unchecked", "boxing" })
   public static ParameterBlockJAI createMeanParameterBlock(RenderedImage source, ROI roi, int h_sampling, int v_sampling) {
      String name = "mean";
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source,
                                                                     Pair.makePair("roi", roi),
                                                                     Pair.makePair("xPeriod", h_sampling),
                                                                     Pair.makePair("yPeriod", v_sampling));
      return pb;
      }


//-----------------
// multiply
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>multiply</em>.
    * @param   source0   the first source image.
    * @param   source1   the second source image.
    * @return   the parameter block.
    */
   @SuppressWarnings("nls")
   public static ParameterBlockJAI createMultiplyParameterBlock(RenderedImage source0, RenderedImage source1) {
      String name = "multiply";
      String mode = RenderedRegistryMode.MODE_NAME;
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, mode);
      if (null != source0) {
         pb.setSource("source0", source0);
         }
      if (null != source1) {
         pb.setSource("source1", source1);
         }
      return pb;
      }


//-----------------
// multiplycomplex
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>multiplycomplex</em>.
    * @param   source0   the first source image.
    * @param   source1   the second source image.
    * @return   the parameter block.
    */
   @SuppressWarnings("nls")
   public static ParameterBlockJAI createMultiplyComplexParameterBlock(RenderedImage source0, RenderedImage source1) {
      String name = "multiplycomplex";
      String mode = RenderedRegistryMode.MODE_NAME;
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, mode);
      if (null != source0) {
         pb.setSource("source0", source0);
         }
      if (null != source1) {
         pb.setSource("source1", source1);
         }
      return pb;
      }


//-----------------
// multiplyconst
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>multiplyconst</em>.
    * @param   source   the source image.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createMultiplyConstParameterBlock(RenderedImage source) {
      double[] constants = new double[] { 1.0, };
      ParameterBlockJAI pb = ParameterBlockUtil.createMultiplyConstParameterBlock(source, constants);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>multiplyconst</em>.
    * @param   source   the source image.
    * @param   constants   the constants to be multiplied.
    * @return   the parameter block.
    */
   @SuppressWarnings({ "nls", "unchecked" })
   public static ParameterBlockJAI createMultiplyConstParameterBlock(RenderedImage source, double[] constants) {
      String name = "multiplyconst";
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source,
                                                                     Pair.makePair("constants", constants));
      return pb;
      }


//-----------------
// null
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>null</em>.
    * @param   source   the source image.
    * @return   the parameter block.
    */
   @SuppressWarnings("nls")
   public static ParameterBlockJAI createNullParameterBlock(RenderedImage source) {
      String name = "null";
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>null</em>.
    * @param   source   the source image.
    * @return   the parameter block.
    */
   @SuppressWarnings("nls")
   public static ParameterBlockJAI createNullParameterBlock(RenderableImage source) {
      String name = "null";
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source);
      return pb;
      }


//-----------------
// periodic shift
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>periodicshift</em>.
    * @param   source   the source image.
    * @return   the parameter block.
    */
   @SuppressWarnings("boxing")
   public static ParameterBlockJAI createPeriodicShiftParameterBlock(RenderedImage source) {
      int width = source.getWidth();
      int height = source.getHeight();
      int dx = width / 2;
      int dy = height / 2;
      ParameterBlockJAI pb = ParameterBlockUtil.createPeriodicShiftParameterBlock(source, dx, dy);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>periodicshift</em>.
    * @param   source   the source image.
    * @param   dx   the displacement in the <em>x</em> direction.
    * @param   dy   the displacement in the <em>y</em> direction.
    * @return   the parameter block.
    */
   @SuppressWarnings({ "nls", "unchecked" })
   public static ParameterBlockJAI createPeriodicShiftParameterBlock(RenderedImage source, Integer dx, Integer dy) {
      String name = "periodicshift";
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source,
                                                                     Pair.makePair("shiftX", dx),
                                                                     Pair.makePair("shiftY", dy));
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>periodicshift</em>.
    * @param   source   the source image.
    * @return   the parameter block.
    */
   @SuppressWarnings("boxing")
   public static ParameterBlockJAI createPeriodicShiftParameterBlock(RenderableImage source) {
      float width = source.getWidth();
      float height = source.getHeight();
      int dx = (int) (width / 2.0f);
      int dy = (int) (height / 2.0f);
      ParameterBlockJAI pb = ParameterBlockUtil.createPeriodicShiftParameterBlock(source, dx, dy);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>periodicshift</em>.
    * @param   source   the source image.
    * @param   dx   the displacement in the <em>x</em> direction.
    * @param   dy   the displacement in the <em>y</em> direction.
    * @return   the parameter block.
    */
   @SuppressWarnings({ "nls", "unchecked" })
   public static ParameterBlockJAI createPeriodicShiftParameterBlock(RenderableImage source, Integer dx, Integer dy) {
      String name = "periodicshift";
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source,
                                                                     Pair.makePair("shiftX", dx),
                                                                     Pair.makePair("shiftY", dy));
      return pb;
      }


//-----------------
// rescale
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>rescale</em>.
    * @param   source   the source image.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createRescaleParameterBlock(RenderedImage source) {
      double[] constants = new double[] { 1.0, };
      double[] offsets = new double[] { 0.0, };
      ParameterBlockJAI pb = ParameterBlockUtil.createRescaleParameterBlock(source, constants, offsets);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>scale</em>.
    * @param   source   the source image.
    * @param   constants    the per-band constants to multiply by.
    * @param   offsets   the per-band offsets to be added.
    * @return   the parameter block.
    */
   @SuppressWarnings({ "nls", "unchecked" })
   public static ParameterBlockJAI createRescaleParameterBlock(RenderedImage source, double[] constants, double[] offsets) {
      String name = "rescale";
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source,
                                                                     Pair.makePair("offsets", offsets),
                                                                     Pair.makePair("constants", constants));
      return pb;
      }

//-----------------
// scale
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>scale</em>.
    * @param   source   the source image.
    * @param   s_x   the scale factor along the <em>x</em> axis.
    * @param   s_y   the scale factor along the <em>y</em> axis.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createScaleParameterBlock(RenderedImage source, float s_x, float s_y) {
      float t_x = 0.0f;
      float t_y = 0.0f;
      ParameterBlockJAI pb = ParameterBlockUtil.createScaleParameterBlock(source, s_x, s_y, t_x, t_y);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>scale</em>.
    * @param   source   the source image.
    * @param   s_x   the scale factor along the <em>x</em> axis.
    * @param   s_y   the scale factor along the <em>y</em> axis.
    * @param   t_x   the translation distance along the <em>x</em> axis.
    * @param   t_y   the translation distance along the <em>y</em> axis.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createScaleParameterBlock(RenderedImage source, float s_x, float s_y, float t_x, float t_y) {
      Interpolation interpolation = null;
      ParameterBlockJAI pb = ParameterBlockUtil.createScaleParameterBlock(source, s_x, s_y, t_x, t_y, interpolation);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>scale</em>.
    * @param   source   the source image.
    * @param   s_x   the scale factor along the <em>x</em> axis.
    * @param   s_y   the scale factor along the <em>y</em> axis.
    * @param   interpolation    the interpolation.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createScaleParameterBlock(RenderedImage source, float s_x, float s_y, Interpolation interpolation) {
      float t_x = 0.0f;
      float t_y = 0.0f;
      ParameterBlockJAI pb = ParameterBlockUtil.createScaleParameterBlock(source, s_x, s_y, t_x, t_y, interpolation);
      return pb;
      }

   /**
    * Creates a parameter block for the core JAI operation <em>scale</em>.
    * @param   source   the source image.
    * @param   s_x   the scale factor along the <em>x</em> axis.
    * @param   s_y   the scale factor along the <em>y</em> axis.
    * @param   t_x   the translation distance along the <em>x</em> axis.
    * @param   t_y   the translation distance along the <em>y</em> axis.
    * @param   interpolation    the interpolation.
    * @return   the parameter block.
    */
   @SuppressWarnings({ "nls", "unchecked", "boxing" })
   public static ParameterBlockJAI createScaleParameterBlock(RenderedImage source, float s_x, float s_y, float t_x, float t_y, Interpolation interpolation) {
      String name = "scale";
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source,
                                                                     Pair.makePair("xScale", s_x),
                                                                     Pair.makePair("yScale", s_y),
                                                                     Pair.makePair("xTrans", t_x),
                                                                     Pair.makePair("yTrans", t_y));
      if (null != interpolation) {
         pb.setParameter("interpolation", interpolation);
         }
      return pb;
      }


//-----------------
// subsampleaverage
//-----------------

   /**
    * Creates a parameter block for the core JAI operation <em>subsampleaverage</em>.
    * @param   source   the source image.
    * @param   s_x   the scale factor along the <em>x</em> axis.
    * @param   s_y   the scale factor along the <em>y</em> axis.
    * @return   the parameter block.
    */
   @SuppressWarnings({ "nls", "boxing", "unchecked" })
   public static ParameterBlockJAI createSubSampleAverageParameterBlock(RenderedImage source, double s_x, double s_y) {
      String name = "subsampleaverage";
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source,
                                                                     Pair.makePair("scaleX", s_x),
                                                                     Pair.makePair("scaleY", s_y));
      return pb;
      }


//-----------------
// subtract
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>subtract</em>.
    * @param   source0   the first source image.
    * @param   source1   the second source image.
    * @return   the parameter block.
    */
   @SuppressWarnings("nls")
   public static ParameterBlockJAI createSubtractParameterBlock(RenderedImage source0, RenderedImage source1) {
      String name = "subtract";
      String mode = RenderedRegistryMode.MODE_NAME;
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, mode);
      if (null != source0) {
         pb.setSource("source0", source0);
         }
      if (null != source1) {
         pb.setSource("source1", source1);
         }
      return pb;
      }


//-----------------
// subtractconst
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>subtractconst</em>.
    * @param   source   the source image.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createSubtractConstParameterBlock(RenderedImage source) {
      double constant = 0.0;
      ParameterBlockJAI pb = ParameterBlockUtil.createSubtractConstParameterBlock(source, constant);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>subtractconst</em>.
    * @param   source   the source image.
    * @param   constant   the constant to be subtracted.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createSubtractConstParameterBlock(RenderedImage source, double constant) {
      double[] constants = new double[] { constant, };
      ParameterBlockJAI pb = ParameterBlockUtil.createSubtractConstParameterBlock(source, constants);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>subtractconst</em>.
    * @param   source   the source image.
    * @param   constants   the constants to be subtracted.
    * @return   the parameter block.
    */
   @SuppressWarnings({ "nls", "unchecked" })
   public static ParameterBlockJAI createSubtractConstParameterBlock(RenderedImage source, double[] constants) {
      String name = "subtractconst";
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, source,
                                                                     Pair.makePair("constants", constants));
      pb.setParameter("constants", constants);
      return pb;
      }


//-----------------
// url
//-----------------

   /**
    * Creates a parameter block for core JAI operation <em>url</em>.
    * @param   url   the location of the image data.
    * @return   the parameter block.
    */
   public static ParameterBlockJAI createUrlParameterBlock(URL url) {
      ImageDecodeParam param = null;
      ParameterBlockJAI pb = ParameterBlockUtil.createUrlParameterBlock(url, param);
      return pb;
      }

   /**
    * Creates a parameter block for core JAI operation <em>scale</em>.
    * @param   url   the location of the image data.
    * @param   param   decoding parameters.
    * @return   the parameter block.
    */
   @SuppressWarnings({ "nls", "unchecked" })
   public static ParameterBlockJAI createUrlParameterBlock(URL url, ImageDecodeParam param) {
      String name = "url";
      ParameterBlockJAI pb = ParameterBlockUtil.createParameterBlock(name, (RenderedImage) null,
                                                                     Pair.makePair("URL", url),
                                                                     Pair.makePair("param", param));
      return pb;
      }

   }
